#region license
# This file is part of Grawlix.
# 
# Grawlix is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
# 
# Grawlix is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with Grawlix.  If not, see
# <http://www.gnu.org/licenses/>.
#endregion

"""Control over the client side of the network."""

namespace Grawlix.Client
import Grawlix.Meta
import Grawlix.Services
import System
import System.Threading
import Lidgren.Library.Network

[Disposable(SharedCleanup: Shutdown)]
transient class NetworkClient:
"""Clientside controller."""
	
	def constructor():
	"""
	Start up services for the client.
	Param world: The world this net is part of.
	"""
		netLog = NetLog()
		netLog.IgnoreTypes = NetLogEntryTypes.None
		netLog.IsOutputToFileEnabled = false
		netLog.LogEvent += WriteLog
		nac = NetAppConfiguration("Grawlix")
		_client = NetClient(nac, netLog)
		_client.StatusChanged += (
			EventHandler[of NetStatusEventArgs](StatusChanged))
	
	private def WriteLog(sender as object, args as NetLogEventArgs):
	"""
	Write an entry to a log.
	Param sender: The log to write to.
	Param args: The log information.
	"""
		if args.Entry.Type & NetLogEntryTypes.Error:
			log Error, "${args.Entry.Where}: ${args.Entry.What}"
		elif args.Entry.Type & NetLogEntryTypes.Warning:
			log Warn, "${args.Entry.Where}: ${args.Entry.What}"
		elif args.Entry.Type & NetLogEntryTypes.Debug:
			log Debug, "${args.Entry.Where}: ${args.Entry.What}"
		else:
			log Info, "${args.Entry.Where}: ${args.Entry.What}"
	
	private def Shutdown():
	"""Get rid of the connection."""
		if _client is not null:
			client = _client
			_client = null
			client.Shutdown("Disposing of the client.")
	
	def Connect(host as string, port as int):
	"""
	Connect to the specified server.
	Param host: The hostname or IP to connect to.
	Param port: The port to connect to.
	"""
		Disconnect("Starting a new connection.")
		log Info, "Client starting on ${host}:${port}."
		_client.Connect(host, port)
		msg = NetMessage()
		msg.Write("Hello Client, I See you are able to talk to me," +
            " I Can Talk to you Too!")
		_client.SendMessage(msg, NetChannel.ReliableUnordered)
		_client.FlushMessages()
		Thread.MemoryBarrier()
	
	def Disconnect(reason as string):
	"""
	Dispose of and close the connection.
	Param reason: The reason for the connection close.
	"""
		if Connected:
			log Info, "Client disconnecting: ${reason}"
			_client.Disconnect("Client disconnecting.")
			Thread.MemoryBarrier()
	
	private def StatusChanged(sender as object, args as NetStatusEventArgs):
		if args.Connection.Status == NetConnectionStatus.Connecting:
			log Info, "Connecting to server..."
		elif args.Connection.Status == NetConnectionStatus.Connected:
			log Info, "Connected to server"
		elif args.Connection.Status == NetConnectionStatus.Disconnected:
			log Info, "Disconnected from server"
	
	def Update(elapsed as timespan):
	"""
	Receive networking events.
	Param elapsed: Time elapsed since last update.
	"""
		if Connected:
			_client.Heartbeat()
			msg as NetMessage
			while ((msg = _client.ReadMessage()) != null):
				truemsg as string = msg.ReadString()
				log Info, "Got a message. Content: \"${truemsg}\""
	
	def Output():
	"""Send out world network packets."""
		pass
	
	Connected as bool:
	"""Whether the connection is active."""
		get:
			return _client.Status != NetConnectionStatus.Disconnected
	
	[property(Game)]
	[IgnoreDisposal]
	private _game as Game
	"""The model of the game world."""
	
	[IgnoreDisposal]
	private _client as NetClient
	"""The client connection."""






